package org.liaohailong.library.db.builder

import android.text.TextUtils
import org.liaohailong.library.db.model.ColumnInfo
import org.liaohailong.library.db.util.Utility
import java.lang.reflect.Field

/**
 * Author: liaohailong
 * Date: 2019/4/3
 * Time: 3:55 PM
 * Description: 建表
 **/
class SQLHelperImpl : AbSQLHelper() {

    override fun getCreateTableIfNotExistsSQL(): String {
        val sql = StringBuilder()
        val table = getTable()
        val primaryKey = getPrimaryKey()
        val columns = mutableListOf<ColumnInfo>().apply { addAll(getAllColumns()) }

        val removed = mutableListOf<ColumnInfo>()
        columns.forEach { if (TextUtils.equals(it.name, primaryKey)) removed.add(it) }
        columns.removeAll(removed)

        sql.append("CREATE TABLE IF NOT EXISTS").append(" ").append(table).append("(")
                .append(primaryKey)
                .append(" INTEGER ")
                .append(" PRIMARY KEY ")
                .append(" AUTOINCREMENT")
                .append(",")

        for (i in 0 until columns.size) {
            val column = columns[i]
            sql.append(column.name).append(" ").append(column.type)
            if (column.notNull) {
                sql.append(" ").append("NOT NULL")
            }
            sql.append(" ").append("DEFAULT")
            when (column.type) {
                SQLHelper.TEXT -> sql.append(" ").append("'").append(column.default).append("'")
                SQLHelper.INTEGER, SQLHelper.LONG, SQLHelper.REAL -> sql.append(" ").append(column.default)
            }

            if (i < columns.size - 1) sql.append(",")
        }
        sql.append(")")
        return sql.toString()
    }

    override fun checkTableIfExistSQL(): String {
        val sql = StringBuilder()
        val table = getTable()

        sql.append("SELECT * FROM sqlite_master WHERE type='table' and name='").append(table).append("'")
        return sql.toString()
    }

    override fun getRenameTableToTempSQL(tempTableName: String): String {
        val sql = StringBuilder()
        val table = getTable()

        sql.append("ALTER TABLE ").append(table).append(" RENAME TO ").append(tempTableName)
        return sql.toString()
    }

    override fun getTransferTableSQL(columns: List<String>, tempTableName: String): String {
        if (columns.isEmpty()) {
            return ""
        }

        val sql = StringBuilder()
        val table = getTable()

        sql.append("INSERT INTO ").append(table).append(" SELECT ")
        for (column in columns) {
            sql.append(" ").append(column).append(",")
        }
        sql.deleteCharAt(sql.length - 1)

        sql.append(" FROM ").append(tempTableName)

        return sql.toString()
    }

    override fun getDropTableSQL(table: String): String {
        val sql = StringBuilder()
        sql.append("DROP TABLE ").append(table)
        return sql.toString()
    }


    override fun <T> getMultipleInsertSQL(insert: MutableList<T>): String {
        val sql = StringBuilder()
        val table = getTable()
        val primaryKey = getPrimaryKey()
        val allColumns = getAllColumns()
        val columns: MutableList<ColumnInfo> = mutableListOf()
        for (allColumn in allColumns) {
            if (TextUtils.equals(primaryKey, allColumn.name)) {
                continue
            }
            columns.add(allColumn)
        }

        sql.append("INSERT INTO ").append(table).append("(")

        for (column in columns) {
            sql.append(column.name).append(",")
        }
        sql.deleteCharAt(sql.length - 1)
        sql.append(") VALUES")

        val columnTypeMap = mutableMapOf<String, String>()
        for (column in columns) {
            columnTypeMap[column.name] = column.type
        }

        //反射域缓存，减轻cpu压力
        //key = 列名 value = class字段（域）
        val firstData = insert[0] as Any
        val columnFields = Utility.getFieldListByColumn(firstData, columns)

        for (item in insert) {
            sql.append("(")
            for (columnField in columnFields) {

                val name = columnField.name
                val field = columnField.value as Field

                when (columnTypeMap[name]) {
                    SQLHelper.INTEGER -> {
                        val intValue = field.getInt(item)
                        sql.append(intValue).append(",")
                    }
                    SQLHelper.LONG -> {
                        val longValue = field.getLong(item)
                        sql.append(longValue).append(",")
                    }
                    SQLHelper.REAL -> {
                        val realValue = field.getDouble(item)
                        sql.append(realValue).append(",")
                    }
                    SQLHelper.TEXT -> {
                        val stringValue = field.get(item).toString()
                        sql.append("'").append(stringValue).append("',")
                    }
                }
            }
            sql.deleteCharAt(sql.length - 1)
            sql.append("),")
        }
        sql.deleteCharAt(sql.length - 1)
        return sql.toString()
    }
}